package tests;

import abstractions.HangmanAbstraction;
import abstractions.HangmanSpecification;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public abstract class JUnit_HangmanAbstraction {

	
	HangmanAbstraction hangmanForTest;

	/**
	 * This method needs to be overridden in the concrete test class in order to
	 * intialise the hangman game with the word to be found to be "test"
	 * @throws Exception
	 */
	@Before
	public abstract void setUp() throws Exception;
	
	private void initAssert(){
		for (int i =0; i<hangmanForTest.lettersFound.length;i++)
			Assert.assertFalse(hangmanForTest.lettersFound[i]);
		
		for (int i =0; i<hangmanForTest.lettersTried.length;i++)
			Assert.assertFalse(hangmanForTest.lettersTried[i]);
		
		Assert.assertEquals(hangmanForTest.currentWord, "test");
		Assert.assertEquals(hangmanForTest.errorCount, 0);
	}
	
	
	@After
	public void tearDown() throws Exception {
		hangmanForTest = null;
	}
	
	
	/**
	 * We make the assumption that the hangman game has been initialised with the word "test"
	 */
	@Test
	public void test_tryLetter_win(){
		
        initAssert();
		
	    hangmanForTest.tryLetter('t');
	    Assert.assertEquals(hangmanForTest.errorCount,0);
	    Assert.assertTrue(hangmanForTest.lettersFound[0]);
	    Assert.assertFalse(hangmanForTest.lettersFound[1]);
	    Assert.assertFalse(hangmanForTest.lettersFound[2]);
	    Assert.assertTrue(hangmanForTest.lettersFound[3]);
	    Assert.assertTrue(hangmanForTest.lettersTried[19]);
	    
	    hangmanForTest.tryLetter('e');
	    Assert.assertEquals(hangmanForTest.errorCount,0);
	    Assert.assertTrue(hangmanForTest.lettersFound[1]);
	    Assert.assertTrue(hangmanForTest.lettersTried[4]);
   
	    hangmanForTest.tryLetter('s');
	    Assert.assertEquals(hangmanForTest.errorCount,0);
	    Assert.assertTrue(hangmanForTest.lettersFound[2]);
	    Assert.assertTrue(hangmanForTest.lettersTried[18]);

	}
	
	/**
	 * We make the assumption that the hangman game has been initialised with the word "test"
	 */
	@Test
	public void test_tryLetter_loss(){
		
		initAssert();
		char letter ='e';
		for (int i =0; i< HangmanSpecification.ERROR_MAX; i++){
			letter++;
			hangmanForTest.tryLetter(letter);
			Assert.assertEquals(hangmanForTest.errorCount,i+1);
		}
		
		for (int i =0; i<hangmanForTest.lettersFound.length;i++)
			Assert.assertFalse(hangmanForTest.lettersFound[i]);
		
					
	}
	
	/**
	 * We make the assumption that the hangman game has been initialised with the word "test"
	 */
	@Test (expected = IllegalStateException.class)
	public void test_tryLetter_illegalStateException(){
		
		initAssert();
		char letter ='e';
		for (int i =0; i<= HangmanSpecification.ERROR_MAX+1; i++){
			letter++;
			hangmanForTest.tryLetter(letter);
		}
	}
	
	/**
	 * We make the assumption that the hangman game has been initialised with the word "test"
	 */
	@Test (expected = IllegalArgumentException.class)
	public void test_tryLetter_illegalArgumentException(){
		
		initAssert();
		
		char not_in_alphabet = HangmanSpecification.ALPHABET_TO;
		not_in_alphabet++;
		hangmanForTest.tryLetter(not_in_alphabet);
	}
}
